package pers.litao.bit.order.service.impl;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.UUID;
import cn.hutool.json.JSON;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import io.jsonwebtoken.Claims;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import pers.litao.bit.commons.dto.UserDTO;
import pers.litao.bit.commons.entities.order.DistributionEntity;
import pers.litao.bit.commons.entities.order.OrderEntity;
import pers.litao.bit.commons.entities.order.SalesEntity;
import pers.litao.bit.commons.entities.priduct.GoodsEntity;
import pers.litao.bit.commons.entities.priduct.LabelEntity;
import pers.litao.bit.commons.entities.priduct.PictureEntity;
import pers.litao.bit.commons.entities.user.AddressEntity;
import pers.litao.bit.commons.entities.user.UserInfoEntity;
import pers.litao.bit.commons.utils.*;
import pers.litao.bit.commons.vo.order.*;
import pers.litao.bit.commons.vo.product.GoodsVo;
import pers.litao.bit.order.dao.OrderMapper;
import pers.litao.bit.order.openfeign.GoodsFeignService;
import pers.litao.bit.order.openfeign.UserFeignService;
import pers.litao.bit.order.service.DistributionService;
import pers.litao.bit.order.service.OrderService;
import pers.litao.bit.order.service.SalesService;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @author 李涛
 * @date 2020-12-05 13:42
 */
@Service
@Slf4j
public class OrderServiceImpl extends ServiceImpl<OrderMapper, OrderEntity> implements OrderService {

    @Autowired
    private GoodsFeignService goodsFeignService;

    @Autowired
    private UserFeignService userFeignService;

    @Autowired
    private DistributionService distributionService;

    @Autowired
    private SalesService salesService;

    /**
     * 新建购物订单
     *
     * @param orderEntity 实
     * @return r
     */
    @Override
    public R saveOrder(OrderEntity orderEntity, LoginUserInfo loginUserInfo) {
        if (null == loginUserInfo) {
            log.error("用户未登录操作" + SysUtil.getClientInfo().buildInfo());
            return R.error(Constant.ResponseCode.TOKEM_INVALID.getCode(),
                    Constant.ResponseCode.TOKEM_INVALID.getMsg(), null);
        }
        // 供应商不能购买商品
        if (loginUserInfo.getIdentity() == 1) {
            log.error("用户身份供应商不能购买商品" + loginUserInfo.info() + SysUtil.getClientInfo().buildInfo());
            return R.error(Constant.ResponseCode.SUPPLIER_CANT_PAYGOODS.getCode(),
                    Constant.ResponseCode.SUPPLIER_CANT_PAYGOODS.getMsg(), null);
        }
        // RPC查询商品信息
        R r = goodsFeignService.getGoodsById(orderEntity.getGoodsId());
        JSON parse = JSONUtil.parse(r);
        GoodsVo goodsData = parse.getByPath("data", GoodsVo.class);
        // 计算总价格
        BigDecimal money = goodsData.getPrice().multiply(BigDecimal.valueOf(orderEntity.getNum()));
        orderEntity.setMoney(money);
        orderEntity.setSupplierId(goodsData.getUserId());
        orderEntity.setPrice(goodsData.getPrice());
        orderEntity.setRetailPrice(goodsData.getRetailPrice());
        orderEntity.setRetailersId(loginUserInfo.getUserId());
        orderEntity.setCreateTime(System.currentTimeMillis());
        String format = DateUtil.format(new Date(), "yyyyMMddHHmmss");
        // 生成订单编号
        String orderNo = loginUserInfo.getUserId() + format + Math.abs(UUID.randomUUID().hashCode());
        orderEntity.setOrderNo(orderNo);
        log.info("用户成功新建订单"+loginUserInfo.info()+SysUtil.getClientInfo().buildInfo());
        this.save(orderEntity);
        return R.ok();
    }

    /**
     * 获取零售商订单列表
     *
     * @param current
     * @return
     */
    @Override
    public R getOrderList(Long current, LoginUserInfo loginUserInfo) {
        // 用户未登录
        if (null == loginUserInfo) {
            log.error("用户未登录操作" + SysUtil.getClientInfo().buildInfo());
            return R.error(Constant.ResponseCode.TOKEM_INVALID.getCode(),
                    Constant.ResponseCode.TOKEM_INVALID.getMsg(), null);
        }
        // 零售商identity == 0
        if (loginUserInfo.getIdentity() == 0) {
            Page<OrderEntity> page = new Page<>();
            // 分页参数
            page.setSize(Constant.RETAIL_ORDER_SIZE);
            page.setCurrent(current);
            // 根据时间降序查询
            this.baseMapper.selectPage(page, new QueryWrapper<OrderEntity>()
                    .eq("retailers_id", loginUserInfo.getUserId())
                    .orderByDesc("create_time"));
            List<OrderEntity> orders = page.getRecords();
            // 遍历并保存订单的商品ID和用户ID
            Long[] userIds = new Long[orders.size()];
            Long[] goodsIds = new Long[orders.size()];
            for (int i = 0; i < orders.size(); i++) {
                userIds[i] = orders.get(i).getSupplierId();
                goodsIds[i] = orders.get(i).getGoodsId();
            }
            // RPC远程批量查询商品信息和用户信息，比单个查询效率好太多
            R goodsListBatch = goodsFeignService.getGoodsListBatch(goodsIds);
            R userList = userFeignService.getUserList(userIds);
            List<GoodsVo> goodsVoList = JSONUtil.parseArray(JSONUtil.parse(goodsListBatch).getByPath("data")).toList(GoodsVo.class);
            List<UserDTO> userDTOList = JSONUtil.parseArray(JSONUtil.parse(userList).getByPath("data")).toList(UserDTO.class);
            List<OrderVo> data = orders.stream()
                    .map(m -> {
                        OrderVo orderVo = new OrderVo();
                        BeanUtils.copyProperties(m, orderVo);
                        // 根据商品ID获取商品信息
                        GoodsVo goodsData = getGoodsVo(goodsVoList, m.getGoodsId());
                        orderVo.setGoodsName(goodsData.getGoodsName());
                        // 设置订单展示图片
                        orderVo.setPicture(JSONUtil.parseArray(goodsData.getPictures())
                                .toList(PictureEntity.class).get(0).getUrl());
                        // 根据
                        UserDTO userDTO = getUserDTO(userDTOList, m.getSupplierId());
                        orderVo.setAddress(userDTO.getUserInputAddress());
                        orderVo.setUserName(userDTO.getName());
                        orderVo.setPhone(userDTO.getPhone());
                        return orderVo;
                    })
                    .collect(Collectors.toList());
            Map<String, Object> map = new HashMap<>();
            map.put("orderData", data);
            map.put("size", page.getTotal());
            log.info("用户请求成功" +loginUserInfo.info() + SysUtil.getClientInfo().buildInfo());
            return R.ok(map);
        }
        return R.ok();
    }

    /**
     * 获取供应商订单列表
     *
     * @param current
     * @return
     */
    @Override
    public R getSupplierOrder(Long current, Map<String,Long> params,LoginUserInfo loginUserInfo) {
        // 用户未登录
        if (null == loginUserInfo) {
            log.error("用户未登录操作" + SysUtil.getClientInfo().buildInfo());
            return R.error(Constant.ResponseCode.TOKEM_INVALID.getCode(),
                    Constant.ResponseCode.TOKEM_INVALID.getMsg(), null);
        }
        // 供应商 identity == 1
        if (loginUserInfo.getIdentity() == 1) {
            Page<OrderEntity> page = new Page<>();
            // 分页参数
            page.setSize(Constant.SUPPLIER_ORDER_SIZE);
            page.setCurrent(current);
            // 订单状态升序，创建时间降序查询
            QueryWrapper<OrderEntity> queryWrapper= new QueryWrapper<>();
            if(params.containsKey("begin") && params.containsKey("end")){
                Object o1 = params.get("begin");
                Object o2 = params.get("end");
                Long begin = Long.valueOf(o1.toString());
                Long end = Long.valueOf(o2.toString());
                queryWrapper.ge("create_time", begin);
                queryWrapper.lt("create_time", DateUtil.offsetDay(new Date(end), 1).getTime());
            }
            this.baseMapper.selectPage(page, queryWrapper
                    .eq("supplier_id", loginUserInfo.getUserId())
                    .orderByAsc("order_status")
                    .orderByDesc("create_time"));
            List<OrderEntity> orders = page.getRecords();
            // 未有订单
            if (orders.size() == 0) {
                Map<String, Object> map = new HashMap<>();
                map.put("orderData", new ArrayList<OrderVo>());
                map.put("size", 0);
                return R.ok(map);
            }
            // 保存订单的商品ID和用户ID
            Long[] userIds = new Long[orders.size()];
            Long[] goodsIds = new Long[orders.size()];
            for (int i = 0; i < orders.size(); i++) {
                userIds[i] = orders.get(i).getRetailersId();
                goodsIds[i] = orders.get(i).getGoodsId();
            }
            // RPC远程批量查询商品信息和用户信息，比单个查询效率好太多
            R goodsListBatch = goodsFeignService.getGoodsListBatch(goodsIds);
            R userList = userFeignService.getUserList(userIds);
            List<GoodsVo> goodsVoList = JSONUtil.parseArray(JSONUtil.parse(goodsListBatch).getByPath("data")).toList(GoodsVo.class);
            List<UserDTO> userDTOList = JSONUtil.parseArray(JSONUtil.parse(userList).getByPath("data")).toList(UserDTO.class);
            List<OrderVo> data = orders.stream()
                    .map(m -> {
                        OrderVo orderVo = new OrderVo();
                        BeanUtils.copyProperties(m, orderVo);
                        // 根据商品ID获取商品信息
                        GoodsVo goodsData = getGoodsVo(goodsVoList, m.getGoodsId());
                        orderVo.setGoodsName(goodsData.getGoodsName());
                        // 设置订单展示图片
                        if (goodsData.getPictures() != null && goodsData.getPictures().size() > 0) {
                            orderVo.setPicture(JSONUtil.parseArray(goodsData.getPictures())
                                    .toList(PictureEntity.class).get(0).getUrl());
                        }
                        // 根据商品零售商ID获取零售商信息
                        UserDTO userDTO = getUserDTO(userDTOList, m.getRetailersId());
                        orderVo.setAddress(userDTO.getUserInputAddress());
                        orderVo.setUserName(userDTO.getName());
                        orderVo.setPhone(userDTO.getPhone());
                        return orderVo;
                    })
                    .collect(Collectors.toList());
            Map<String, Object> map = new HashMap<>();
            map.put("orderData", data);
            map.put("size", page.getTotal());
            log.info("用户请求成功" +loginUserInfo.info() + SysUtil.getClientInfo().buildInfo());
            return R.ok(map);
        }
        return R.ok();
    }

    /**
     * 合并配送订单
     *
     * @param orderVos
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public R distributionOrder(List<OrderVo> orderVos, LoginUserInfo loginUserInfo) {
        // 用户未登录
        if (null == loginUserInfo) {
            log.error("用户未登录操作" + SysUtil.getClientInfo().buildInfo());
            return R.error(Constant.ResponseCode.TOKEM_INVALID.getCode(),
                    Constant.ResponseCode.TOKEM_INVALID.getMsg(), null);
        }
        // 保存供应商ID
        Set<Long> supplierIds = new HashSet<>();
        // 保存零售商ID，及需要配送的用户，不重复
        Set<Long> retailersIds = new HashSet<>();
        // 保存订单ID
        List<Long> orders = new ArrayList<>();
        // 批量更新订单状态的实体集合
        List<OrderEntity> updateOrders = new ArrayList<>();
        orderVos.forEach(e -> {
            supplierIds.add(e.getSupplierId());
            retailersIds.add(e.getRetailersId());
            orders.add(e.getId());
            OrderEntity orderEntity = new OrderEntity();
            BeanUtils.copyProperties(e, orderEntity);
            orderEntity.setOrderStatus(1);
            updateOrders.add(orderEntity);
            //    this.baseMapper.updateById(orderEntity);
        });
        // 批量更新订单状态
        this.updateBatchById(updateOrders);
        // 供应商应只有一个，且就是登陆用户
        if (supplierIds.size() == 1 && supplierIds.contains(loginUserInfo.getUserId())) {
            // 保存配送地址地点
            List<AddressPointVo> listAddress = new ArrayList<>();
            // 获取供应商信息
            R r = userFeignService.getUser(loginUserInfo.getUserId());
            JSON parse = JSONUtil.parse(r);
            AddressEntity startAddress = parse.getByPath("data.addressData", AddressEntity.class);
            listAddress.add(new AddressPointVo(startAddress.getUserInputAddress(), startAddress.getPointLng(), startAddress.getPointLat()));
            // 获取零售商信息
            Long[] userIds = new Long[retailersIds.size()];
            retailersIds.toArray(userIds);
            R userList = userFeignService.getUserList(userIds);
            List<UserDTO> userDTOList = JSONUtil.parseArray(JSONUtil.parse(userList).getByPath("data")).toList(UserDTO.class);
            userDTOList.forEach(item -> {
                listAddress.add(new AddressPointVo(item.getUserInputAddress(), item.getPointLng(), item.getPointLat()));
            });
            // 生成合并订单
            DistributionEntity distributionEntity = new DistributionEntity();
            distributionEntity.setBeginAddress(listAddress.get(0).getAddress())
                    .setEndAddress(listAddress.get(listAddress.size() - 1).getAddress())
                    .setUserId(loginUserInfo.getUserId())
                    .setOrders(JSONUtil.toJsonStr(orders))
                    .setPoints(JSONUtil.toJsonPrettyStr(listAddress))
                    .setCreateTime(System.currentTimeMillis());
            log.info("合并订单成功" +loginUserInfo.info() + SysUtil.getClientInfo().buildInfo());
            distributionService.save(distributionEntity);
            return R.ok();
        } else {
            log.error("合并订单失效，原因是身份验证失败" +loginUserInfo.info() + SysUtil.getClientInfo().buildInfo());
            return R.error(Constant.ResponseCode.ILLEGAL_OPERATION.getCode(),
                    Constant.ResponseCode.ILLEGAL_OPERATION.getMsg(), null);
        }

    }

    /**
     * 获取订单列表（根据订单IDS）
     *
     * @param ids
     * @return
     */
    @Override
    public R getListByIds(List<Long> ids, LoginUserInfo loginUserInfo) {
        // 用户未登录
        if (null == loginUserInfo) {
            log.error("用户未登录操作" + SysUtil.getClientInfo().buildInfo());
            return R.error(Constant.ResponseCode.TOKEM_INVALID.getCode(),
                    Constant.ResponseCode.TOKEM_INVALID.getMsg(), null);
        }
        List<OrderEntity> orders = this.baseMapper.selectBatchIds(ids);

        Long[] goodsIds = new Long[orders.size()];
        Long[] userIds = new Long[orders.size()];
        for (int i = 0; i < orders.size(); i++) {
            goodsIds[i] = orders.get(i).getGoodsId();
            userIds[i] = orders.get(i).getRetailersId();
        }
        // 批量查询商品信息和用户信息
        R goodsListBatch = goodsFeignService.getGoodsListBatch(goodsIds);
        R userList = userFeignService.getUserList(userIds);
        List<GoodsVo> goodsVoList = JSONUtil.parseArray(JSONUtil.parse(goodsListBatch).getByPath("data")).toList(GoodsVo.class);
        List<UserDTO> userDTOList = JSONUtil.parseArray(JSONUtil.parse(userList).getByPath("data")).toList(UserDTO.class);
        List<OrderVo> data = orders.stream()
                .map(m -> {
                    OrderVo orderVo = new OrderVo();
                    BeanUtils.copyProperties(m, orderVo);
                    //Long goodsId = m.getGoodsId();
                    // Long retailersId = m.getRetailersId();
                    //   R r = goodsFeignService.getGoodsById(goodsId);
                    //  JSON parse = JSONUtil.parse(r);
                    //   GoodsVo goodsData = parse.getByPath("data", GoodsVo.class);
                    GoodsVo goodsData = getGoodsVo(goodsVoList, m.getGoodsId());
                    orderVo.setGoodsName(goodsData.getGoodsName());
                    orderVo.setPicture(JSONUtil.parseArray(goodsData.getPictures())
                            .toList(PictureEntity.class).get(0).getUrl());
                    // R r1 = userFeignService.getUser(retailersId);
                    //  JSON parse1 = JSONUtil.parse(r1);
                    //      System.out.println(parse1);
                    // UserInfoEntity byPathUser = parse1.getByPath("data.userData", UserInfoEntity.class);
                    //  AddressEntity byPathAddress = parse1.getByPath("data.addressData", AddressEntity.class);
                    UserDTO userDTO = getUserDTO(userDTOList, m.getRetailersId());
                    orderVo.setAddress(userDTO.getUserInputAddress());
                    orderVo.setUserName(userDTO.getName());
                    orderVo.setPhone(userDTO.getPhone());
                    return orderVo;
                })
                .collect(Collectors.toList());
        log.info("用户请求成功" +loginUserInfo.info() + SysUtil.getClientInfo().buildInfo());
        return R.ok(data);
    }

    /**
     * 订单提交
     *
     * @param ids
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public R orderComplete(List<Long> ids, LoginUserInfo loginUserInfo) {
        // 未登录
        if (null == loginUserInfo) {
            log.error("用户未登录操作" + SysUtil.getClientInfo().buildInfo());
            return R.error(Constant.ResponseCode.TOKEM_INVALID.getCode(),
                    Constant.ResponseCode.TOKEM_INVALID.getMsg(), null);
        }
        List<OrderEntity> orderEntities = this.baseMapper.selectBatchIds(ids);
        // 下标
        AtomicInteger index = new AtomicInteger(0);
        ids.forEach(e -> {
            if (orderEntities.get(index.get()).getOrderStatus() != 2) {
                OrderEntity orderEntity = new OrderEntity();
                orderEntity.setId(e);
                orderEntity.setOrderStatus(2);
                this.baseMapper.updateById(orderEntity);
            }
            // 订单供应商ID和登陆ID不一致。
            if (!orderEntities.get(index.get()).getSupplierId().equals(loginUserInfo.getUserId())) {
                throw new RuntimeException("非法操作");
            }
            index.set(index.intValue() + 1);
        });
        log.info("订单成功提交"+loginUserInfo.info() + SysUtil.getClientInfo().buildInfo());
        return R.ok();
    }

    /**
     * 取消订单
     *
     * @param id
     * @return
     */
    @Override
    public R cancelOrder(Long id, LoginUserInfo loginUserInfo) {
        // 未登录
        if (null == loginUserInfo) {
            log.error("用户未登录操作" + SysUtil.getClientInfo().buildInfo());
            return R.error(Constant.ResponseCode.TOKEM_INVALID.getCode(),
                    Constant.ResponseCode.TOKEM_INVALID.getMsg(), null);
        }
        OrderEntity orderEntity = this.baseMapper.selectById(id);
        // 零售商ID和登陆ID不一致。
        if (!loginUserInfo.getUserId().equals(orderEntity.getRetailersId())) {
            log.error("身份验证错误"+loginUserInfo.info() + SysUtil.getClientInfo().buildInfo());
            return R.error(Constant.ResponseCode.ILLEGAL_OPERATION.getCode(),
                    Constant.ResponseCode.ILLEGAL_OPERATION.getMsg(), null);
        }
        orderEntity.setOrderStatus(3);
        this.baseMapper.updateById(orderEntity);
        log.info("订单ID为" +id+"成功取消"+loginUserInfo.info() + SysUtil.getClientInfo().buildInfo());
        return R.ok();
    }

    /**
     * 设置零售价
     *
     * @param id
     * @param price
     * @return
     */
    @Override
    public R setRetailPrice(Long id, BigDecimal price, LoginUserInfo loginUserInfo) {
        // 未登录
        if (null == loginUserInfo) {
            log.error("用户未登录操作" + SysUtil.getClientInfo().buildInfo());
            return R.error(Constant.ResponseCode.TOKEM_INVALID.getCode(),
                    Constant.ResponseCode.TOKEM_INVALID.getMsg(), null);
        }
        OrderEntity orderEntity = this.baseMapper.selectById(id);
        // 零售商ID和登陆ID不一致。
        if (!loginUserInfo.getUserId().equals(orderEntity.getRetailersId())) {
            log.error("身份验证错误"+loginUserInfo.info() + SysUtil.getClientInfo().buildInfo());
            return R.error(Constant.ResponseCode.ILLEGAL_OPERATION.getCode(),
                    Constant.ResponseCode.ILLEGAL_OPERATION.getMsg(), null);
        }
        orderEntity.setIprice(price);
        this.baseMapper.updateById(orderEntity);
        log.info("订单ID为" +id+"成功设置零售价为"+price.toString() + "元"+loginUserInfo.info() + SysUtil.getClientInfo().buildInfo());
        return R.ok();
    }

    /**
     * 设置已出售数量
     *
     * @param id
     * @param num
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public R setNum(Long id, Integer num, LoginUserInfo loginUserInfo) {
        // 未登录
        if (null == loginUserInfo) {
            log.error("用户未登录操作" + SysUtil.getClientInfo().buildInfo());
            return R.error(Constant.ResponseCode.TOKEM_INVALID.getCode(),
                    Constant.ResponseCode.TOKEM_INVALID.getMsg(), null);
        }
        OrderEntity orderEntity = this.baseMapper.selectById(id);
        // 零售商ID和登陆ID不一致。
        if (!loginUserInfo.getUserId().equals(orderEntity.getRetailersId())) {
            log.error("身份验证错误"+loginUserInfo.info() + SysUtil.getClientInfo().buildInfo());
            return R.error(Constant.ResponseCode.ILLEGAL_OPERATION.getCode(),
                    Constant.ResponseCode.ILLEGAL_OPERATION.getMsg(), null);
        }
        // 设置出售数量
        SalesEntity salesEntity = new SalesEntity();
        salesEntity.setNum(num)
                .setOrderId(id)
                .setUserId(loginUserInfo.getUserId())
                .setCreateTime(System.currentTimeMillis())
                .setMoney(orderEntity.getIprice().multiply(BigDecimal.valueOf(num)));
        orderEntity.setSnum(num);
        salesService.save(salesEntity);
        log.info("订单ID为" +id+"成功设置数量为"+num +loginUserInfo.info() + SysUtil.getClientInfo().buildInfo());
        this.baseMapper.updateById(orderEntity);
        return R.ok();
    }

    /**
     * 获取供应商首页三个卡片数据
     *
     * @return
     */
    @Override
    synchronized public R getCard(LoginUserInfo loginUserInfo) {
        // 未登录
        if (null == loginUserInfo) {
            log.error("用户未登录操作" + SysUtil.getClientInfo().buildInfo());
            return R.error(Constant.ResponseCode.TOKEM_INVALID.getCode(),
                    Constant.ResponseCode.TOKEM_INVALID.getMsg(), null);
        }
        // 供应商身份
        if (loginUserInfo.getIdentity() == 1) {
            List<OrderEntity> entities = this.list(new QueryWrapper<OrderEntity>()
                    .eq("supplier_id", loginUserInfo.getUserId()));
            //昨日销售额
            BigDecimal moneySum = entities.stream()
                    .filter(item -> {
                        return item.getCreateTime() >= DateUtil.beginOfDay(DateUtil.offsetDay(DateTime.now(), -1)).getTime()
                                && item.getCreateTime() < DateUtil.beginOfDay(DateTime.now()).getTime();
                    })
                    .filter(item -> {
                        return item.getOrderStatus() < 3;
                    })
                    .map(OrderEntity::getMoney)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            //昨日成交量
            long volume = entities.stream()
                    // 筛选出昨日
                    .filter(item -> {
                        return item.getCreateTime() >= DateUtil.beginOfDay(DateUtil.offsetDay(DateTime.now(), -1)).getTime()
                                && item.getCreateTime() < DateUtil.beginOfDay(DateTime.now()).getTime();
                    })
                    .filter(item -> {
                        return item.getOrderStatus() < 3;
                    })
                    .count();
            //当前未配送
            long undelivered = entities.stream()
                    .filter(item -> {
                        return item.getOrderStatus() == 0;
                    })
                    .count();
            Map<String, Object> map = new HashMap<>();
            map.put("moneySum", moneySum);
            map.put("volume", volume);
            map.put("undelivered", undelivered);
            log.info("用户请求成功" +loginUserInfo.info() + SysUtil.getClientInfo().buildInfo());
            return R.ok(map);
        }
        return R.ok();
    }

    /**
     * 获取历史和昨日成交
     *
     * @return
     */
    @Override
    public R getOrderCount(LoginUserInfo loginUserInfo) {
        // 未登录
        if (null == loginUserInfo) {
            log.error("用户未登录操作" + SysUtil.getClientInfo().buildInfo());
            return R.error(Constant.ResponseCode.TOKEM_INVALID.getCode(),
                    Constant.ResponseCode.TOKEM_INVALID.getMsg(), null);
        }
        Map<String, Object> map = new HashMap<>(2);
        if (loginUserInfo.getIdentity() == 1) {
            // 供应商昨日销量统计
            int yesterdayCount = this.count(
                    new QueryWrapper<OrderEntity>()
                            .eq("supplier_id", loginUserInfo.getUserId())
                            .ge("create_time", DateUtil.beginOfDay(DateUtil.offsetDay(DateUtil.date(), -1)).getTime())
                            .lt("create_time", DateUtil.beginOfDay(DateUtil.date()).getTime())
            );
            // 供应商历史销量统计
            int historyCount = this.count(
                    new QueryWrapper<OrderEntity>()
                            .eq("supplier_id", loginUserInfo.getUserId())
            );
            map.put("yesterdayCount", yesterdayCount);
            map.put("historyCount", historyCount);
        } else {
            // 零售商昨日统计
            int yesterdayCount = this.count(
                    new QueryWrapper<OrderEntity>()
                            .eq("retailers_id", loginUserInfo.getUserId())
                            .ge("create_time", DateUtil.beginOfDay(DateUtil.offsetDay(DateUtil.date(), -1)).getTime())
                            .lt("create_time", DateUtil.beginOfDay(DateUtil.date()).getTime())
            );
            // 零售商历史统计
            int historyCount = this.count(
                    new QueryWrapper<OrderEntity>()
                            .eq("retailers_id", loginUserInfo.getUserId())
            );
            map.put("yesterdayCount", yesterdayCount);
            map.put("historyCount", historyCount);
        }
        log.info("用户请求成功" +loginUserInfo.info() + SysUtil.getClientInfo().buildInfo());
        return R.ok(map);
    }

    /**
     * 零售商盈亏统计
     *
     * @param loginUserInfo
     * @return
     */
    @Override
    public R profitAndLoss(LoginUserInfo loginUserInfo) {
        // 未登录
        if (null == loginUserInfo) {
            log.error("用户未登录操作" + SysUtil.getClientInfo().buildInfo());
            return R.error(Constant.ResponseCode.TOKEM_INVALID.getCode(),
                    Constant.ResponseCode.TOKEM_INVALID.getMsg(), null);
        }
        // 只有零售商才有盈亏统计
        if (loginUserInfo.getIdentity() != 0) {
            log.error("身份验证错误"+loginUserInfo.info() + SysUtil.getClientInfo().buildInfo());
            return R.error(Constant.ResponseCode.SUPPLIER_CANT_PROFIT_AND_LOSS.getCode(),
                    Constant.ResponseCode.SUPPLIER_CANT_PROFIT_AND_LOSS.getMsg(), null);
        }
        List<PieNodeVo> pieNodeVos = new ArrayList<>();
        List<OrderEntity> orderEntities = this.list(new QueryWrapper<OrderEntity>()
                .eq("retailers_id", loginUserInfo.getUserId())
                .lt("order_status", 3));
        BigDecimal history = orderEntities.stream()
                .filter(order -> order.getOrderStatus() == 2 && order.getIprice() != null)
                .map(order -> order.getIprice().multiply(BigDecimal.valueOf(order.getSnum())))
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        pieNodeVos.add(new PieNodeVo("历史总收入", history));
        pieNodeVos.add(new PieNodeVo("未出账中收入（按推荐零售价）",
                orderEntities.stream()
                        .filter(order -> order.getOrderStatus() < 2 && order.getIprice() != null)
                        .map(order -> order.getIprice().multiply(BigDecimal.valueOf(order.getSnum())))
                        .reduce(BigDecimal.ZERO, BigDecimal::add)
        ));
        pieNodeVos.add(new PieNodeVo("历史总支出",
                orderEntities.stream()
                        .filter(order -> order.getOrderStatus() == 2)
                        .map(OrderEntity::getMoney)
                        .reduce(BigDecimal.ZERO, BigDecimal::add)
        ));
        pieNodeVos.add(new PieNodeVo("未出账支出",
                orderEntities.stream()
                        .filter(order -> order.getOrderStatus() < 2)
                        .map(OrderEntity::getMoney)
                        .reduce(BigDecimal.ZERO, BigDecimal::add)
        ));
        log.info("用户请求成功" +loginUserInfo.info() + SysUtil.getClientInfo().buildInfo());
        return R.ok(pieNodeVos);
    }

    /**
     * 零售商销售统计-漏斗图
     * @param loginUserInfo
     * @return
     */
    @Override
    public R funnel(LoginUserInfo loginUserInfo) {
        // 未登录
        if (null == loginUserInfo) {
            log.error("用户未登录操作" + SysUtil.getClientInfo().buildInfo());
            return R.error(Constant.ResponseCode.TOKEM_INVALID.getCode(),
                    Constant.ResponseCode.TOKEM_INVALID.getMsg(), null);
        }
        // 只有零售商才有漏斗图销售统计
        if (loginUserInfo.getIdentity() != 0) {
            log.error("身份验证错误"+loginUserInfo.info() + SysUtil.getClientInfo().buildInfo());
            return R.error(Constant.ResponseCode.SUPPLIER_CANT_FUNNEL.getCode(),
                    Constant.ResponseCode.SUPPLIER_CANT_FUNNEL.getMsg(), null);
        }
        // 查询出的订单
        List<OrderEntity> orderEntities = this.list(new QueryWrapper<OrderEntity>()
                .eq("retailers_id", loginUserInfo.getUserId())
                .eq("order_status", 2));
        // 商品ID集合
        List<Long> goodsIdsList = new ArrayList<>();
        // 计算商品ID对应所销售金额
        Map<Long,BigDecimal> goodsMap = new HashMap<>();
        for(OrderEntity order : orderEntities){
            if(order.getIprice() != null){
                goodsIdsList.add(order.getGoodsId());
                if(goodsMap.containsKey(order.getGoodsId())){
                    goodsMap.put(order.getGoodsId(), goodsMap.get(order.getGoodsId())
                            .add(order.getIprice().multiply(BigDecimal.valueOf(order.getSnum()))) );
                }
                else {
                    goodsMap.put(order.getGoodsId()
                            , order.getIprice().multiply(BigDecimal.valueOf(order.getSnum())));
                }
            }
        }
        // 商品ID数组
        Long[] goodsIds = new Long[goodsIdsList.size()];
        goodsIdsList.toArray(goodsIds);
        // feign接口调用
        R rGoodsList = goodsFeignService.getGoodsListBatch(goodsIds);
        // 商品列表
        List<GoodsEntity> goodsList = JSONUtil.parseArray(rGoodsList.get("data")).toList(GoodsEntity.class);
        // 标签ID列表
        List<Long> labelIdsList = new ArrayList<>();
        for(GoodsEntity goodsEntity : goodsList){
            labelIdsList.add(goodsEntity.getLabelId());
        }
        // 查询标签
        R rLabelList = goodsFeignService.getListLabelByIds(labelIdsList);
        List<LabelEntity> labelList = JSONUtil.parseArray(rLabelList.get("data")).toList(LabelEntity.class);
        Map<Long,String> labelMap = new HashMap<>();
        for(LabelEntity labelEntity : labelList){
            if (!labelMap.containsKey(labelEntity.getId())){
                labelMap.put(labelEntity.getId(), labelEntity.getLabelName());
            }
        }
        // 最终结果
        Map<String,BigDecimal> mapNode = new HashMap<>();
        // 遍历
        for(Map.Entry<Long,BigDecimal> m : goodsMap.entrySet()){
            String name = getLabelName(goodsList,labelMap,m.getKey());
            if(mapNode.containsKey(name)){
                mapNode.put(name, mapNode.get(name).add(m.getValue()));
            }
            else {
                mapNode.put(name,m.getValue());
            }
        }
        List<PieNodeVo> node = mapNode.keySet().stream()
                .map(item -> {
                    PieNodeVo pieNodeVo = new PieNodeVo();
                    pieNodeVo.setName(item);
                    pieNodeVo.setValue(mapNode.get(item));
                    return pieNodeVo;
                }).collect(Collectors.toList());
        log.info("用户请求成功" +loginUserInfo.info() + SysUtil.getClientInfo().buildInfo());
        return R.ok(node);
    }

    /**
     * 供应商统计一周订单量
     *
     * @param loginUserInfo
     * @return
     */
    @Override
    public R getSupplyWeekOrders(LoginUserInfo loginUserInfo) {
        // 未登录
        if (null == loginUserInfo) {
            log.error("用户未登录操作" + SysUtil.getClientInfo().buildInfo());
            return R.error(Constant.ResponseCode.TOKEM_INVALID.getCode(),
                    Constant.ResponseCode.TOKEM_INVALID.getMsg(), null);
        }
        // 只有供应商才有订单统计
        if (loginUserInfo.getIdentity() != 1) {
            log.error("身份验证错误"+loginUserInfo.info() + SysUtil.getClientInfo().buildInfo());
            return R.error(Constant.ResponseCode.SUPPLIER_API.getCode(),
                    Constant.ResponseCode.SUPPLIER_API.getMsg(), null);
        }
        Date date = DateUtil.date();
        // 一周内总订单
        List<OrderEntity> orderEntities = this.list(new QueryWrapper<OrderEntity>()
                .eq("supplier_id", loginUserInfo.getUserId())
                .ge("create_time", DateUtil.beginOfDay(DateUtil.offsetDay(date, -6)).getTime())
                .lt("create_time", DateUtil.beginOfDay(DateUtil.offsetDay(date, 1)).getTime()));
        List<OrderCountVo> orderCountVos = new ArrayList<>();
        for(int i = -6 ; i <= 0 ;i++){
            long startTime = DateUtil.beginOfDay(DateUtil.offsetDay(date, i)).getTime();
            long endTime = DateUtil.beginOfDay(DateUtil.offsetDay(date, i + 1)).getTime();
            long cancelOrder = orderEntities
                    .stream()
                    // 筛选
                    .filter(order -> order.getOrderStatus() == 3
                            && order.getCreateTime() >= startTime
                            && order.getCreateTime() < endTime)
                    .count();
            long commitOrder = orderEntities
                    .stream()
                    .filter(order -> order.getOrderStatus() < 3
                            && order.getCreateTime() >= startTime
                            && order.getCreateTime() < endTime)
                    .count();
            orderCountVos.add(new OrderCountVo(cancelOrder,commitOrder));
        }
        log.info("用户请求成功" +loginUserInfo.info() + SysUtil.getClientInfo().buildInfo());
        return R.ok(orderCountVos);
    }

    /**
     * 订单周销售额统计
     *
     * @param loginUserInfo
     * @return
     */
    @Override
    public R getSupplyWeekMoney(LoginUserInfo loginUserInfo) {
        // 未登录
        if (null == loginUserInfo) {
            log.error("用户未登录操作" + SysUtil.getClientInfo().buildInfo());
            return R.error(Constant.ResponseCode.TOKEM_INVALID.getCode(),
                    Constant.ResponseCode.TOKEM_INVALID.getMsg(), null);
        }
        // 只有供应商才有订单统计
        if (loginUserInfo.getIdentity() != 1) {
            log.error("身份验证错误"+loginUserInfo.info() + SysUtil.getClientInfo().buildInfo());
            return R.error(Constant.ResponseCode.SUPPLIER_API.getCode(),
                    Constant.ResponseCode.SUPPLIER_API.getMsg(), null);
        }
        Date date = DateUtil.date();
        // 一周内总订单
        List<OrderEntity> orderEntities = this.list(new QueryWrapper<OrderEntity>()
                .eq("supplier_id", loginUserInfo.getUserId())
                .ge("create_time", DateUtil.beginOfDay(DateUtil.offsetDay(date, -6)).getTime())
                .lt("create_time", DateUtil.beginOfDay(DateUtil.offsetDay(date, 1)).getTime()));
        // 一周的销售额
        List<BigDecimal> weekMoney = new ArrayList<>();
        for(int i = -6 ; i <= 0 ;i++){
            long startTime = DateUtil.beginOfDay(DateUtil.offsetDay(date, i)).getTime();
            long endTime = DateUtil.beginOfDay(DateUtil.offsetDay(date, i + 1)).getTime();
            BigDecimal dayMoney = orderEntities
                    .stream()
                    // 筛选
                    .filter(order -> order.getOrderStatus() < 3
                            && order.getCreateTime() >= startTime
                            && order.getCreateTime() < endTime)
                    .map(OrderEntity::getMoney)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            weekMoney.add(dayMoney);
        }
        log.info("用户请求成功" +loginUserInfo.info() + SysUtil.getClientInfo().buildInfo());
        return R.ok(weekMoney);
    }

    /**
     * 供应商首页统计图
     *
     * @param loginUserInfo
     * @return
     */
    @Override
    public R getSupplyMain(LoginUserInfo loginUserInfo) {
        // 未登录
        if (null == loginUserInfo) {
            log.error("用户未登录操作" + SysUtil.getClientInfo().buildInfo());
            return R.error(Constant.ResponseCode.TOKEM_INVALID.getCode(),
            Constant.ResponseCode.TOKEM_INVALID.getMsg(), null);
        }
        // 只有供应商才有订单统计
        if (loginUserInfo.getIdentity() != 1) {
            log.error("身份验证错误"+loginUserInfo.info() + SysUtil.getClientInfo().buildInfo());
            return R.error(Constant.ResponseCode.SUPPLIER_API.getCode(),
                    Constant.ResponseCode.SUPPLIER_API.getMsg(), null);
        }
        // 获得每个季度时间
        int year = DateUtil.year(DateUtil.date());
        List<DateTime> qTime = new ArrayList<>();
        DateTime q1BeginTime = DateUtil.parse(year + "-01-01");
        DateTime q2BeginTime = DateUtil.parse(year + "-04-01");
        DateTime q3BeginTime = DateUtil.parse(year + "-07-01");
        DateTime q4BeginTime = DateUtil.parse(year + "-10-01");
        DateTime endTime = DateUtil.parse((year + 1) + "-01-01");
        qTime.add(q1BeginTime);
        qTime.add(q2BeginTime);
        qTime.add(q3BeginTime);
        qTime.add(q4BeginTime);
        qTime.add(endTime);
        // 获得所有订单
        List<OrderEntity> orderEntities = this.list(new QueryWrapper<OrderEntity>()
                .eq("supplier_id", loginUserInfo.getUserId()));
        // 返回的数据
        Map<String,Object> data = new HashMap<>(2);
        // 季度统计
        List<MainOrderVo> qList = new ArrayList<>();
        // 年度统计
        List<MainOrderVo> yearList = new ArrayList<>();
        for(int i = 0 ;i < qTime.size() - 1 ;i++){
            long begin = qTime.get(i).getTime();
            long end = qTime.get(i + 1).getTime();
            qList.add(getOrderInfo(begin, end, orderEntities));

        }
        for(int i = -4;i <= 0;i++){
            long begin = DateUtil.parse((year + i) + "-01-01").getTime();
            long end = DateUtil.parse((year + i + 1) + "-01-01").getTime();
            yearList.add(getOrderInfo(begin, end, orderEntities));
        }
        data.put("qList", qList);
        data.put("yearList", yearList);
        log.info("用户请求成功" +loginUserInfo.info() + SysUtil.getClientInfo().buildInfo());
        return R.ok(data);
    }

    private GoodsVo getGoodsVo(List<GoodsVo> goodsVos, Long goodsId) {
        for (GoodsVo goodsVo : goodsVos) {
            if (goodsVo.getId().equals(goodsId)) {
                return goodsVo;
            }
        }
        return new GoodsVo();
    }

    private UserDTO getUserDTO(List<UserDTO> userDtos, Long userId) {
        for (UserDTO userDTO : userDtos) {
            if (userDTO.getId().equals(userId)) {
                return userDTO;
            }
        }
        return new UserDTO();
    }
    private String getLabelName(List<GoodsEntity> goodsList,Map<Long,String> labelMap, Long goodsId){
        for(GoodsEntity goodsEntity : goodsList){
            if(goodsEntity.getId().equals(goodsId)){
                return labelMap.get(goodsEntity.getLabelId());
            }
        }
        return "";
    }
    private MainOrderVo getOrderInfo(long begin, long end , List<OrderEntity> orderEntities){
        Map<Long,Integer> users = new HashMap<>();
        List<OrderEntity> qOrders = orderEntities
                .stream()
                .filter(order -> order.getCreateTime() >= begin && order.getCreateTime() < end)
                .collect(Collectors.toList());
        // 总订单数
        long allCount = 0L;
        // 有效订单数
        long count = 0L;
        // 总用户
        int allUser = 0;
        // 有效用户
        int user = 0;
        // 总金额
        BigDecimal money = BigDecimal.ZERO;
        for(OrderEntity orderEntity : qOrders){
            allCount += 1L;
            if(orderEntity.getOrderStatus() < 3){
                count += 1L;
                money =  money.add(orderEntity.getMoney());
                // users不存在用户，表示用户未被统计
                if(!users.containsKey(orderEntity.getRetailersId())){
                    allUser += 1;
                    users.put(orderEntity.getRetailersId(),1);
                }
                // users存在用户，value为1,表示用户二次购买未被统计
                else if(users.containsKey(orderEntity.getRetailersId())
                        && users.get(orderEntity.getRetailersId()) == 1){
                    user += 1;
                    users.put(orderEntity.getRetailersId(),2);
                }
            }
        }
        // 计算百分比
        BigDecimal rate = allUser == 0
                ? BigDecimal.ZERO
                : BigDecimal.valueOf(user)
                .divide(BigDecimal.valueOf(allUser).add(BigDecimal.valueOf(user)) , 4,BigDecimal.ROUND_HALF_UP)
                .multiply(BigDecimal.valueOf(100));
        return new MainOrderVo(allCount,count,money,rate);
    }
}
